From 4d4a0212fb3dc7854424084044adbc6642ea6616 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 19 Sep 2017 18:53:32 -0400 Subject: [PATCH] vulkan: Better glyph cache api Move the glyph caching api to something that can support using multiple textures. We now split the text render ops into multiple ops for different textures, and make each op render just a substring of the text node's glyph string. --- gsk/gskvulkancolortextpipeline.c | 36 +++-- gsk/gskvulkancolortextpipelineprivate.h | 4 +- gsk/gskvulkanrenderer.c | 172 +++++++++------------- gsk/gskvulkanrendererprivate.h | 47 +++--- gsk/gskvulkanrenderpass.c | 186 +++++++++++++++--------- gsk/gskvulkantextpipeline.c | 36 +++-- gsk/gskvulkantextpipelineprivate.h | 4 +- 7 files changed, 255 insertions(+), 230 deletions(-) diff --git a/gsk/gskvulkancolortextpipeline.c b/gsk/gskvulkancolortextpipeline.c index 6cca24334e..6f97a8d696 100644 --- a/gsk/gskvulkancolortextpipeline.c +++ b/gsk/gskvulkancolortextpipeline.c @@ -99,15 +99,19 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline * PangoFont *font, PangoGlyphString *glyphs, float x, - float y) + float y, + guint start_glyph, + guint num_glyphs) { GskVulkanColorTextInstance *instances = (GskVulkanColorTextInstance *) data; - int i, count; + int i + int count = 0; int x_position = 0; - float dx, dy, dw, dh; - count = 0; - for (i = 0; i < glyphs->num_glyphs; i++) + for (i = 0; i < start_glyph; i++) + x_position += glyphs->glyphs[i].geometry.width; + + for (; i < num_glyphs; i++) { PangoGlyphInfo *gi = &glyphs->glyphs[i]; @@ -119,17 +123,19 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline * if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)) { GskVulkanColorTextInstance *instance = &instances[count]; + GskVulkanCachedGlyph *glyph; + + glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph); + + instance->tex_rect[0] = glyph->tx; + instance->tex_rect[1] = glyph->ty; + instance->tex_rect[2] = glyph->tw; + instance->tex_rect[3] = glyph->th; - gsk_vulkan_renderer_get_glyph_coords (renderer, font, gi->glyph, - &instance->tex_rect[0], - &instance->tex_rect[1], - &instance->tex_rect[2], - &instance->tex_rect[3], - &dx, &dy, &dw, &dh); - instance->rect[0] = x + cx + dx; - instance->rect[1] = y + cy + dy; - instance->rect[2] = dw; - instance->rect[3] = dh; + instance->rect[0] = x + cx + glyph->draw_x; + instance->rect[1] = y + cy + glyph->draw_y; + instance->rect[2] = glyph->draw_width; + instance->rect[3] = glyph->draw_height; count++; } diff --git a/gsk/gskvulkancolortextpipelineprivate.h b/gsk/gskvulkancolortextpipelineprivate.h index b341abde34..8c4a8c35c4 100644 --- a/gsk/gskvulkancolortextpipelineprivate.h +++ b/gsk/gskvulkancolortextpipelineprivate.h @@ -27,7 +27,9 @@ void gsk_vulkan_color_text_pipeline_collect_vertex_data (Gs PangoFont *font, PangoGlyphString *glyphs, float x, - float y); + float y, + guint start_glyph, + guint num_glyphs); gsize gsk_vulkan_color_text_pipeline_draw (GskVulkanColorTextPipeline *pipeline, VkCommandBuffer command_buffer, gsize offset, diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c index d9739a02cc..281bc2215e 100644 --- a/gsk/gskvulkanrenderer.c +++ b/gsk/gskvulkanrenderer.c @@ -370,22 +370,6 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, return image; } -GskVulkanImage * -gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, - GskVulkanUploader *uploader, - PangoFont *font, - PangoGlyphString *glyphs) -{ - if (self->glyph_cache->image == NULL) - self->glyph_cache->image = gsk_vulkan_image_new_from_data (uploader, - cairo_image_surface_get_data (self->glyph_cache->surface), - cairo_image_surface_get_width (self->glyph_cache->surface), - cairo_image_surface_get_height (self->glyph_cache->surface), - cairo_image_surface_get_stride (self->glyph_cache->surface)); - - return g_object_ref (self->glyph_cache->image); -} - typedef struct _GlyphCacheKey GlyphCacheKey; typedef struct _GlyphCacheValue GlyphCacheValue; @@ -394,53 +378,6 @@ struct _GlyphCacheKey { PangoGlyph glyph; }; -struct _GlyphCacheValue { - float tx; - float ty; - float tw; - float th; - - float draw_x; - float draw_y; - float draw_width; - float draw_height; -}; - -static GlyphCacheValue *glyph_cache_lookup (GlyphCache *cache, - gboolean create, - PangoFont *font, - PangoGlyph glyph); - -void -gsk_vulkan_renderer_get_glyph_coords (GskVulkanRenderer *self, - PangoFont *font, - PangoGlyph glyph, - float *tx, - float *ty, - float *tw, - float *th, - float *dx, - float *dy, - float *dw, - float *dh) -{ - GlyphCacheValue *gv; - - gv = glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph); - - if (gv) - { - *tx = gv->tx; - *ty = gv->ty; - *tw = gv->tw; - *th = gv->th; - *dx = gv->draw_x; - *dy = gv->draw_y; - *dw = gv->draw_width; - *dh = gv->draw_height; - } -} - /*** Glyph cache ***/ static gboolean @@ -477,10 +414,10 @@ glyph_cache_value_free (gpointer v) } static void -add_to_cache (GlyphCache *cache, - PangoFont *font, - PangoGlyph glyph, - GlyphCacheValue *value) +add_to_cache (GlyphCache *cache, + PangoFont *font, + PangoGlyph glyph, + GskVulkanCachedGlyph *value) { cairo_t *cr; cairo_scaled_font_t *scaled_font; @@ -523,16 +460,18 @@ add_to_cache (GlyphCache *cache, value->ty = (cg.y + value->draw_y) / cache->height; value->tw = (float)value->draw_width / cache->width; value->th = (float)value->draw_height / cache->height; + + value->texture_index = 0; } -static GlyphCacheValue * +static GskVulkanCachedGlyph * glyph_cache_lookup (GlyphCache *cache, gboolean create, PangoFont *font, PangoGlyph glyph) { GlyphCacheKey lookup_key; - GlyphCacheValue *value; + GskVulkanCachedGlyph *value; lookup_key.font = font; lookup_key.glyph = glyph; @@ -544,7 +483,9 @@ glyph_cache_lookup (GlyphCache *cache, GlyphCacheKey *key; PangoRectangle ink_rect; - value = g_new (GlyphCacheValue, 1); + value = g_new (GskVulkanCachedGlyph, 1); + + value->texture_index = 0; pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL); pango_extents_to_pixels (&ink_rect, NULL); @@ -555,11 +496,7 @@ glyph_cache_lookup (GlyphCache *cache, value->draw_height = ink_rect.height; if (ink_rect.width > 0 && ink_rect.height > 0) - { - add_to_cache (cache, font, glyph, value); - - g_clear_object (&cache->image); - } + add_to_cache (cache, font, glyph, value); key = g_new (GlyphCacheKey, 1); key->font = g_object_ref (font); @@ -571,23 +508,42 @@ glyph_cache_lookup (GlyphCache *cache, return value; } -void -gsk_vulkan_renderer_cache_glyphs (GskVulkanRenderer *self, - PangoFont *font, - PangoGlyphString *glyphs) +static void +free_glyph_cache (GlyphCache *cache) +{ + g_hash_table_unref (cache->hash_table); + cairo_surface_destroy (cache->surface); + g_free (cache); +} + +static void +dump_glyph_cache_stats (GlyphCache *cache) { - int i; + static gint64 time; + gint64 now; - for (i = 0; i < glyphs->num_glyphs; i++) - { - PangoGlyphInfo *gi = &glyphs->glyphs[i]; + if (!cache->hash_table) + return; - if (gi->glyph != PANGO_GLYPH_EMPTY) - { - if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)) - (void) glyph_cache_lookup (self->glyph_cache, TRUE, font, gi->glyph); - } - } + now = g_get_monotonic_time (); + if (now - time < 1000000) + return; + + time = now; + + cairo_surface_write_to_png (cache->surface, "gsk-glyph-cache.png"); +} + +guint +gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self, + PangoFont *font, + PangoGlyph glyph) +{ + GskVulkanCachedGlyph *value; + + value = glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph); + + return value->texture_index; } static GlyphCache * @@ -608,28 +564,30 @@ create_glyph_cache (void) return cache; } -static void -free_glyph_cache (GlyphCache *cache) +GskVulkanImage * +gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, + GskVulkanUploader *uploader, + guint index) { - g_hash_table_unref (cache->hash_table); - cairo_surface_destroy (cache->surface); - g_free (cache); + if (self->glyph_cache->image == NULL) + self->glyph_cache->image = gsk_vulkan_image_new_from_data (uploader, + cairo_image_surface_get_data (self->glyph_cache->surface), + cairo_image_surface_get_width (self->glyph_cache->surface), + cairo_image_surface_get_height (self->glyph_cache->surface), + cairo_image_surface_get_stride (self->glyph_cache->surface)); + + return g_object_ref (self->glyph_cache->image); } -static void -dump_glyph_cache_stats (GlyphCache *cache) +GskVulkanCachedGlyph * +gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self, + PangoFont *font, + PangoGlyph glyph) { - static gint64 time; - gint64 now; - - if (!cache->hash_table) - return; - - now = g_get_monotonic_time (); - if (now - time < 1000000) - return; + GlyphCacheKey lookup_key; - time = now; + lookup_key.font = font; + lookup_key.glyph = glyph; - cairo_surface_write_to_png (cache->surface, "gsk-glyph-cache.png"); + return g_hash_table_lookup (self->glyph_cache->hash_table, &lookup_key); } diff --git a/gsk/gskvulkanrendererprivate.h b/gsk/gskvulkanrendererprivate.h index 25b90e6c29..0f954e3cbb 100644 --- a/gsk/gskvulkanrendererprivate.h +++ b/gsk/gskvulkanrendererprivate.h @@ -25,26 +25,33 @@ GskVulkanImage * gsk_vulkan_renderer_ref_texture_image (GskVulk GskTexture *texture, GskVulkanUploader *uploader); -GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, - GskVulkanUploader *uploader, - PangoFont *font, - PangoGlyphString *glyphs); - -void gsk_vulkan_renderer_get_glyph_coords (GskVulkanRenderer *self, - PangoFont *font, - PangoGlyph glyph, - float *tx, - float *ty, - float *tw, - float *th, - float *dx, - float *dy, - float *dw, - float *dh); - -void gsk_vulkan_renderer_cache_glyphs (GskVulkanRenderer *renderer, - PangoFont *font, - PangoGlyphString *glyphs); +typedef struct +{ + guint texture_index; + + float tx; + float ty; + float tw; + float th; + + int draw_x; + int draw_y; + int draw_width; + int draw_height; +} GskVulkanCachedGlyph; + +guint gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *renderer, + PangoFont *font, + PangoGlyph glyph); + +GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, + GskVulkanUploader *uploader, + guint index); + +GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self, + PangoFont *font, + PangoGlyph glyph); + G_END_DECLS diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index 1c22f233f5..d6dc158231 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -25,6 +25,7 @@ typedef union _GskVulkanOp GskVulkanOp; typedef struct _GskVulkanOpRender GskVulkanOpRender; +typedef struct _GskVulkanOpText GskVulkanOpText; typedef struct _GskVulkanOpPushConstants GskVulkanOpPushConstants; typedef enum { @@ -60,6 +61,21 @@ struct _GskVulkanOpRender gsize descriptor_set_index; /* index into descriptor sets array for the right descriptor set to bind */ }; +struct _GskVulkanOpText +{ + GskVulkanOpType type; + GskRenderNode *node; /* node that's the source of this op */ + GskVulkanPipeline *pipeline; /* pipeline to use */ + GskRoundedRect clip; /* clip rect (or random memory if not relevant) */ + GskVulkanImage *source; /* source image to render */ + gsize vertex_offset; /* offset into vertex buffer */ + gsize vertex_count; /* number of vertices */ + gsize descriptor_set_index; /* index into descriptor sets array for the right descriptor set to bind */ + guint texture_index; + guint start_glyph; + guint num_glyphs; +}; + struct _GskVulkanOpPushConstants { GskVulkanOpType type; @@ -72,6 +88,7 @@ union _GskVulkanOp GskVulkanOpType type; GskVulkanOpRender render; GskVulkanOpPushConstants constants; + GskVulkanOpText text; }; struct _GskVulkanRenderPass @@ -197,37 +214,59 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, return; case GSK_TEXT_NODE: - gsk_vulkan_renderer_cache_glyphs (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), - gsk_text_node_get_font (node), - gsk_text_node_get_glyphs (node)); + { + PangoFont *font = gsk_text_node_get_font (node); + PangoGlyphString *glyphs = gsk_text_node_get_glyphs (node); + PangoGlyph glyph; + int i; + guint texture_index; + GskVulkanRenderer *renderer = GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)); + + if (font_has_color_glyphs (font)) + { + if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT; + else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) + pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP; + else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) + pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP_ROUNDED; + else + FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type); + op.type = GSK_VULKAN_OP_COLOR_TEXT; + } + else + { + if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + pipeline_type = GSK_VULKAN_PIPELINE_TEXT; + else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) + pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP; + else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) + pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP_ROUNDED; + else + FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type); + op.type = GSK_VULKAN_OP_TEXT; + } + op.text.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type); - if (font_has_color_glyphs (gsk_text_node_get_font (node))) - { - if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) - pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT; - else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) - pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP; - else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) - pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP_ROUNDED; - else - FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type); - op.type = GSK_VULKAN_OP_COLOR_TEXT; - } - else - { - if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) - pipeline_type = GSK_VULKAN_PIPELINE_TEXT; - else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) - pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP; - else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) - pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP_ROUNDED; - else - FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type); - op.type = GSK_VULKAN_OP_TEXT; - } - op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type); - g_array_append_val (self->render_ops, op); - return; + i = 0; + texture_index = gsk_vulkan_renderer_cache_glyph (renderer, font, glyphs->glyphs[0].glyph); + while (i < glyphs->num_glyphs) + { + op.text.start_glyph = i; + op.text.texture_index = texture_index; + + do { + i++; + glyph = glyphs->glyphs[i].glyph; + if (glyph != PANGO_GLYPH_EMPTY && !(glyph & PANGO_GLYPH_UNKNOWN_FLAG)) + texture_index = gsk_vulkan_renderer_cache_glyph (renderer, font, glyph); + } while (i < glyphs->num_glyphs && op.text.texture_index == texture_index); + + op.text.num_glyphs = i - op.text.start_glyph; + g_array_append_val (self->render_ops, op); + } + return; + } case GSK_TEXTURE_NODE: if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) @@ -600,11 +639,10 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, case GSK_VULKAN_OP_TEXT: case GSK_VULKAN_OP_COLOR_TEXT: { - op->render.source = gsk_vulkan_renderer_ref_glyph_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), - uploader, - gsk_text_node_get_font (op->render.node), - gsk_text_node_get_glyphs (op->render.node)); - gsk_vulkan_render_add_cleanup_image (render, op->render.source); + op->text.source = gsk_vulkan_renderer_ref_glyph_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), + uploader, + op->text.texture_index); + gsk_vulkan_render_add_cleanup_image (render, op->text.source); } break; @@ -690,15 +728,15 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self) break; case GSK_VULKAN_OP_TEXT: - op->render.vertex_count = gsk_vulkan_text_pipeline_count_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->render.pipeline), - pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node))); - n_bytes += op->render.vertex_count; + op->text.vertex_count = gsk_vulkan_text_pipeline_count_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->text.pipeline), + op->text.num_glyphs); + n_bytes += op->text.vertex_count; break; case GSK_VULKAN_OP_COLOR_TEXT: - op->render.vertex_count = gsk_vulkan_color_text_pipeline_count_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->render.pipeline), - pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node))); - n_bytes += op->render.vertex_count; + op->text.vertex_count = gsk_vulkan_color_text_pipeline_count_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->render.pipeline), + op->text.num_glyphs); + n_bytes += op->text.vertex_count; break; case GSK_VULKAN_OP_COLOR: @@ -777,32 +815,36 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, case GSK_VULKAN_OP_TEXT: { - op->render.vertex_offset = offset + n_bytes; - gsk_vulkan_text_pipeline_collect_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->render.pipeline), + op->text.vertex_offset = offset + n_bytes; + gsk_vulkan_text_pipeline_collect_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->text.pipeline), data + n_bytes + offset, GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), - &op->render.node->bounds, - gsk_text_node_get_font (op->render.node), - gsk_text_node_get_glyphs (op->render.node), - gsk_text_node_get_color (op->render.node), - gsk_text_node_get_x (op->render.node), - gsk_text_node_get_y (op->render.node)); - n_bytes += op->render.vertex_count; + &op->text.node->bounds, + gsk_text_node_get_font (op->text.node), + gsk_text_node_get_glyphs (op->text.node), + gsk_text_node_get_color (op->text.node), + gsk_text_node_get_x (op->text.node), + gsk_text_node_get_y (op->text.node), + op->text.start_glyph, + op->text.num_glyphs); + n_bytes += op->text.vertex_count; } break; case GSK_VULKAN_OP_COLOR_TEXT: { - op->render.vertex_offset = offset + n_bytes; - gsk_vulkan_color_text_pipeline_collect_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->render.pipeline), + op->text.vertex_offset = offset + n_bytes; + gsk_vulkan_color_text_pipeline_collect_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->text.pipeline), data + n_bytes + offset, GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)), - &op->render.node->bounds, - gsk_text_node_get_font (op->render.node), - gsk_text_node_get_glyphs (op->render.node), - gsk_text_node_get_x (op->render.node), - gsk_text_node_get_y (op->render.node)); - n_bytes += op->render.vertex_count; + &op->text.node->bounds, + gsk_text_node_get_font (op->text.node), + gsk_text_node_get_glyphs (op->text.node), + gsk_text_node_get_x (op->text.node), + gsk_text_node_get_y (op->text.node), + op->text.start_glyph, + op->text.num_glyphs); + n_bytes += op->text.vertex_count; } break; @@ -948,8 +990,6 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, case GSK_VULKAN_OP_FALLBACK_CLIP: case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP: case GSK_VULKAN_OP_SURFACE: - case GSK_VULKAN_OP_TEXT: - case GSK_VULKAN_OP_COLOR_TEXT: case GSK_VULKAN_OP_TEXTURE: case GSK_VULKAN_OP_OPACITY: case GSK_VULKAN_OP_BLUR: @@ -957,6 +997,10 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, op->render.source); break; + case GSK_VULKAN_OP_TEXT: + case GSK_VULKAN_OP_COLOR_TEXT: + op->text.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, op->text.source); + break; default: g_assert_not_reached (); case GSK_VULKAN_OP_COLOR: @@ -1027,9 +1071,9 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, break; case GSK_VULKAN_OP_TEXT: - if (current_pipeline != op->render.pipeline) + if (current_pipeline != op->text.pipeline) { - current_pipeline = op->render.pipeline; + current_pipeline = op->text.pipeline; vkCmdBindPipeline (command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, gsk_vulkan_pipeline_get_pipeline (current_pipeline)); @@ -1039,7 +1083,7 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, (VkBuffer[1]) { gsk_vulkan_buffer_get_buffer (vertex_buffer) }, - (VkDeviceSize[1]) { op->render.vertex_offset }); + (VkDeviceSize[1]) { op->text.vertex_offset }); current_draw_index = 0; } @@ -1049,20 +1093,20 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, 0, 1, (VkDescriptorSet[1]) { - gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index) + gsk_vulkan_render_get_descriptor_set (render, op->text.descriptor_set_index) }, 0, NULL); current_draw_index += gsk_vulkan_text_pipeline_draw (GSK_VULKAN_TEXT_PIPELINE (current_pipeline), - command_buffer, - current_draw_index, pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node))); + command_buffer, + current_draw_index, op->text.num_glyphs); break; case GSK_VULKAN_OP_COLOR_TEXT: - if (current_pipeline != op->render.pipeline) + if (current_pipeline != op->text.pipeline) { - current_pipeline = op->render.pipeline; + current_pipeline = op->text.pipeline; vkCmdBindPipeline (command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, gsk_vulkan_pipeline_get_pipeline (current_pipeline)); @@ -1072,7 +1116,7 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, (VkBuffer[1]) { gsk_vulkan_buffer_get_buffer (vertex_buffer) }, - (VkDeviceSize[1]) { op->render.vertex_offset }); + (VkDeviceSize[1]) { op->text.vertex_offset }); current_draw_index = 0; } @@ -1082,14 +1126,14 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, 0, 1, (VkDescriptorSet[1]) { - gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index) + gsk_vulkan_render_get_descriptor_set (render, op->text.descriptor_set_index) }, 0, NULL); current_draw_index += gsk_vulkan_color_text_pipeline_draw (GSK_VULKAN_COLOR_TEXT_PIPELINE (current_pipeline), command_buffer, - current_draw_index, pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node))); + current_draw_index, op->text.num_glyphs); break; case GSK_VULKAN_OP_OPACITY: diff --git a/gsk/gskvulkantextpipeline.c b/gsk/gskvulkantextpipeline.c index def6c6e95f..76c9988689 100644 --- a/gsk/gskvulkantextpipeline.c +++ b/gsk/gskvulkantextpipeline.c @@ -107,15 +107,19 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline, PangoGlyphString *glyphs, const GdkRGBA *color, float x, - float y) + float y, + guint start_glyph, + guint num_glyphs) { GskVulkanTextInstance *instances = (GskVulkanTextInstance *) data; - int i, count; + int i + int count = 0; int x_position = 0; - float dx, dy, dw, dh; - count = 0; - for (i = 0; i < glyphs->num_glyphs; i++) + for (i = 0; i < start_glyph; i++) + x_position += glyphs->glyphs[i].geometry.width; + + for (; i < num_glyphs; i++) { PangoGlyphInfo *gi = &glyphs->glyphs[i]; @@ -127,17 +131,19 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline, if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)) { GskVulkanTextInstance *instance = &instances[count]; + GskVulkanCachedGlyph *glyph; + + glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph); + instance->tex_rect[0] = glyph->tx; + instance->tex_rect[1] = glyph->ty; + instance->tex_rect[2] = glyph->tw; + instance->tex_rect[3] = glyph->th; + + instance->rect[0] = x + cx + glyph->draw_x; + instance->rect[1] = y + cy + glyph->draw_y; + instance->rect[2] = glyph->draw_width; + instance->rect[3] = glyph->draw_height; - gsk_vulkan_renderer_get_glyph_coords (renderer, font, gi->glyph, - &instance->tex_rect[0], - &instance->tex_rect[1], - &instance->tex_rect[2], - &instance->tex_rect[3], - &dx, &dy, &dw, &dh); - instance->rect[0] = x + cx + dx; - instance->rect[1] = y + cy + dy; - instance->rect[2] = dw; - instance->rect[3] = dh; instance->color[0] = color->red; instance->color[1] = color->green; instance->color[2] = color->blue; diff --git a/gsk/gskvulkantextpipelineprivate.h b/gsk/gskvulkantextpipelineprivate.h index a41846d57a..09a58c0468 100644 --- a/gsk/gskvulkantextpipelineprivate.h +++ b/gsk/gskvulkantextpipelineprivate.h @@ -28,7 +28,9 @@ void gsk_vulkan_text_pipeline_collect_vertex_data (GskVulka PangoGlyphString *glyphs, const GdkRGBA *color, float x, - float y); + float y, + guint start_glyph, + guint num_glyphs); gsize gsk_vulkan_text_pipeline_draw (GskVulkanTextPipeline *pipeline, VkCommandBuffer command_buffer, gsize offset, -- 2.30.2